import { DocumentNode, FieldNode, FragmentDefinitionNode, InputObjectTypeDefinitionNode, InputValueDefinitionNode, NamedTypeNode, NonNullTypeNode, ObjectTypeDefinitionNode, OperationDefinitionNode } from 'graphql'
import { getEntityListFC, getInputFieldFC } from './antd/FieldTypeFCTmpl'



export const getEditTSX = (astNode: DocumentNode, documents: Array<{ document: DocumentNode }>): string => {


    const searchAttributesFragment = (documents[0].document.definitions.find(d => d.kind === "FragmentDefinition" && d.name.value.endsWith("SearchAttributes"))) as FragmentDefinitionNode

    const searchAttributesFragmentFields
        = searchAttributesFragment.selectionSet.selections
            .filter(s => s.kind === "Field" && !(s.name.value === 'id' || s.name.value === '__typename'))
            .map(s => (s as FieldNode).name.value)

    const typeName = searchAttributesFragment.typeCondition.name.value

    type FieldTypes = { [fieldName: string]: string }
    const allFieldTypes: FieldTypes = {}
    const objectTypeDefinitionList = (astNode.definitions.find(n => n.kind === "ObjectTypeDefinition" && n.name.value === typeName) as ObjectTypeDefinitionNode)
        .fields?.filter(f => f.type.kind === "NamedType")
    
    objectTypeDefinitionList?.forEach(f => {
        allFieldTypes[f.name?.value] = (f.type as NamedTypeNode).name?.value
    })

    const operationNodeList = (documents[0].document.definitions.filter(d => d.kind === "OperationDefinition")) as Array<OperationDefinitionNode>

    const searchOperationNode = operationNodeList.find(o => o.operation === "query" && o.name?.value.startsWith("search"))
    const createOperationNode = operationNodeList.find(o => o.operation === "mutation" && o.name?.value.startsWith("create"))
    const updateOperationNode = operationNodeList.find(o => o.operation === "mutation" && o.name?.value.startsWith("update"))
    const deleteOperationNode = operationNodeList.find(o => o.operation === "mutation" && o.name?.value.startsWith("delete"))

    const createVariableTypes: FieldTypes = {}
    createOperationNode?.variableDefinitions?.forEach(
        v => createVariableTypes[v.variable.name.value] = ((v.type as NonNullTypeNode).type as NamedTypeNode).name.value
    )

  

    type InputVariableList = Array<{ path: string, name: string, type: string }>
    const createInputVariableList: InputVariableList = []
    Object.keys(createVariableTypes).forEach(vName => {
        (astNode.definitions.find(n => n.kind === "InputObjectTypeDefinition" && n.name?.value === createVariableTypes[vName]) as InputObjectTypeDefinitionNode)
            .fields?.forEach(f => {
                if (f.kind === "InputValueDefinition")
                    createInputVariableList.push({ path: vName, name: f.name?.value, type: (f.type as NamedTypeNode).name?.value })
            })
    })

    // return JSON.stringify(createVariableTypes, null, 2)

    let inputFieldFCList: string = ""
    createInputVariableList.forEach(v => {
        inputFieldFCList += getInputFieldFC(v.path, v.name, v.type)
    })

    //  return result


    let elemToColumnMapString: string = ""
    let columnToInputMapString: string = ""
    const listColumns = [
        {
            title: "id",
            key: 'id',
            dataIndex: 'id',
        }
    ]
    searchAttributesFragmentFields.forEach(f => {
        listColumns.push({ title: f, key: f, dataIndex: f })

        if (allFieldTypes[f] === 'Boolean')
            elemToColumnMapString += f + ": <Checkbox checked={elem." + f + "!} disabled={true} />,\n"
        else
            elemToColumnMapString += f + ": elem." + f + ",\n"

        columnToInputMapString += f + ": data." + f + ",\n"

    })
    listColumns.push(
        {
            title: "actions",
            key: 'actions',
            dataIndex: 'actions',
        }
    )


    return getEntityListFC(
        typeName.slice(3),
        inputFieldFCList,
        JSON.stringify(listColumns, null, 2),
        elemToColumnMapString,
        columnToInputMapString
    )

}

